/*
 * File:        UDP_Assembler.h
 * Authors:     Jonathan Kotker (ee122-bw) and Shaan Mulchandani (ee122-bv)
 * Description: This header file contains the methods required to assemble
 *              a message into a UDP packet to be sent across the network.
 */

#ifndef _UDP_ASSEMBLER_H
#define	_UDP_ASSEMBLER_H

#include "UDP_Contents.h"
#include "constants.h"
#include <sys/socket.h>

/*
 * Sets the HP/EXP into the provided packet bytes starting at position `x'.
 */
void set_hp_exp_id(unsigned long int hpExp, char* packetbytes, int x) {
    *((unsigned long int *) (packetbytes + x)) = htonl(hpExp);
};

void set_ports(unsigned short int port, char* packetbytes, int x) {
    *((unsigned short int *) (packetbytes + x)) = htons(port);
}

int assembleUdpPacket(char* arr, UDP_Contents* content) {
    switch (content->messageType) {
        case STORAGE_LOCATION_REQUEST:
        {
            int i;
            for (i = 0; i < 16; i++)
                arr[i] = 0x00;

            arr[0] = STORAGE_LOCATION_REQUEST;
            set_hp_exp_id(content->id, arr, 1);

            for (i = 0; i < 9; i++) {
                if (content->playerName[i] == 0x00)
                    break;
                arr[i + 5] = content->playerName[i];
            }
            return 16;
        }

        case STORAGE_LOCATION_RESPONSE:
        {
            int i;
            for (i = 0; i < 12; i++)
                arr[i] = 0x00;

            arr[0] = STORAGE_LOCATION_RESPONSE;
            set_hp_exp_id(content->id, arr, 1);
            set_hp_exp_id(content->server_ip_add, arr, 5);
            set_ports(content->server_udp_port, arr, 9);
            return 12;
        }

        case SERVER_AREA_REQUEST:
        {
            int i;
            for (i = 0; i < 8; i++)
                arr[i] = 0x00;

            arr[0] = SERVER_AREA_REQUEST;
            set_hp_exp_id(content->id, arr, 1);
            arr[5] = content->xLoc;
            arr[6] = content->yLoc;

            return 8;
        }

        case SERVER_AREA_RESPONSE:
        {
            int i;
            for (i = 0; i < 16; i++)
                arr[i] = 0x00;

            arr[0] = SERVER_AREA_RESPONSE;
            set_hp_exp_id(content->id, arr, 1);
            set_hp_exp_id(content->server_ip_add, arr, 5);
            set_ports(content->server_tcp_port, arr, 9);
            arr[11] = content->minX;
            arr[12] = content->maxX;
            arr[13] = content->minY;
            arr[14] = content->maxY;

            return 16;
        }

        case PLAYER_STATE_REQUEST:
        {
            int i;
            for (i = 0; i < 16; i++)
                arr[i] = 0x00;

            arr[0] = PLAYER_STATE_REQUEST;
            set_hp_exp_id(content->id, arr, 1);

            for (i = 0; i < 9; i++) {
                if (content->playerName[i] == 0x00)
                    break;
                arr[i + 5] = content->playerName[i];
            }

            return 16;
        }

        case PLAYER_STATE_RESPONSE:
        {
            int i;
            for (i = 0; i < 28; i++)
                arr[i] = 0x00;

            arr[0] = PLAYER_STATE_RESPONSE;
            set_hp_exp_id(content->id, arr, 1);

            for (i = 0; i < 9; i++) {
                if (content->playerName[i] == 0x00)
                    break;
                arr[i + 5] = content->playerName[i];
            }

            set_hp_exp_id(content->hp, arr, 15);
            set_hp_exp_id(content->exp, arr, 19);

            arr[23] = content->xLoc;
            arr[24] = content->yLoc;
            
            return 28;

        }

        case SAVE_STATE_REQUEST:
        {
            int i;
            for (i = 0; i < 28; i++)
                arr[i] = 0x00;

            arr[0] = SAVE_STATE_REQUEST;
            set_hp_exp(content->id, arr, 1);

            for (i = 0; i < 9; i++) {
                if (content->playerName[i] == 0x00)
                    break;
                arr[i + 5] = content->playerName[i];
            }

            set_hp_exp_id(content->hp, arr, 15);
            set_hp_exp_id(content->exp, arr, 19);

            arr[23] = content->xLoc;
            arr[24] = content->yLoc;

            return 28;
        }

        case SAVE_STATE_RESPONSE:
        {
            int i;
            for (i = 0; i < 8; i++)
                arr[i] = 0x00;

            arr[0] = SAVE_STATE_RESPONSE;
            set_hp_exp_id(content->id, arr, 1);
            arr[5] = content->errorCode;

            return 8;
        }
    }
}

#endif	/* _UDP_ASSEMBLER_H */

